import React, { useEffect, useMemo, useState } from "react";
import cn from "classnames";

import { DateTimePicker } from "@/ui/DateTimePicker/DateTimePicker";
import { Button } from "@/ui/Button/Button";
import { Tab, formatDate } from "@/ui/RangeTimePicker/helpers";

import cls from "./RangeTimePicker.module.scss";
import { DateIcon } from "./icons";
import { TimePicker } from "./TimePicker";

type Props = {
  startDate?: Date;
  endDate?: Date;
  minDate?: Date | null;
  maxDate?: Date | null;
  inline?: boolean;
  hideButtons?: boolean;
  hideFooter?: boolean;
  onlyStart?: boolean;
  onlyEnd?: boolean;
  onChange?: (d: [Date | undefined, Date | undefined]) => void;
  onConfirmClick?: (d: [Date | undefined, Date | undefined]) => void;
  onResetClick?: () => void;
  collapse?: boolean;
  separate?: boolean;
  fromPreview?: Date;
  toPreview?: Date;
  openInitially?: boolean;
  openEnd?: boolean;
  realtorButtons?: boolean;
};

export const RangeTimePicker: React.FC<Props> = ({
  startDate,
  endDate,
  minDate,
  maxDate,
  onChange,
  onlyStart,
  onlyEnd,
  inline,
  hideButtons,
  hideFooter,
  onConfirmClick,
  onResetClick,
  collapse,
  separate,
  fromPreview,
  toPreview,
  openInitially,
  openEnd,
  realtorButtons,
}) => {
  // Date
  const [start, setStart] = useState<Date | undefined>(startDate);
  const [end, setEnd] = useState<Date | undefined>(endDate);

  const from = start ? formatDate(start, "PPpp") : "";
  const to = end ? formatDate(end, "PPpp") : "";

  // Tab
  const [isOpen, setOpen] = useState(openInitially || openEnd || false);
  const [tab, setTab] = useState<Tab | undefined>(() => {
    if (onlyEnd || openEnd) return Tab.end;
    if (onlyStart || openInitially) return Tab.start;
    return undefined;
  });

  const onTabClick = (tb: Tab) => {
    return () => {
      if (tb === tab && isOpen) {
        setOpen(false);
        return;
      }
      setTab(tb);
      setOpen(true);
    };
  };

  // Time
  const dateHours = useMemo(() => {
    if (tab === Tab.start && start) {
      return start.getHours();
    }

    if (tab === Tab.end && end) {
      return end.getHours();
    }
    return 0;
  }, [tab, start, end]);

  const dateMinutes = useMemo(() => {
    if (tab === Tab.start && start) {
      return start.getMinutes();
    }

    if (tab === Tab.end && end) {
      return end.getMinutes();
    }

    return 0;
  }, [tab, start, end]);

  const updateTime = (h: number, m: number) => {
    if (tab === Tab.start) {
      const date = start ? new Date(start) : new Date();
      date.setHours(h);
      date.setMinutes(m);
      date.setSeconds(0);
      date.setMilliseconds(0);
      if (end && date > end) setEnd(undefined);
      setStart(date);
    } else if (tab === Tab.end) {
      if (!start) return;
      const date = end ? new Date(end) : new Date(start);
      date.setHours(h);
      date.setMinutes(m);
      date.setSeconds(0);
      date.setMilliseconds(0);
      setEnd(date);
    }
  };

  const onConfirm = () => {
    if (onChange) onChange([start, end]);
    setOpen(false);
    if (onConfirmClick) onConfirmClick([start, end]);
  };

  const onReset = () => {
    setStart(undefined);
    setEnd(undefined);
    if (onChange) onChange([undefined, undefined]);
    setOpen(false);
    if (onResetClick) onResetClick();
  };

  useEffect(() => {
    if (onChange) onChange([start, end]);
  }, [end, onChange, start]);

  const separatePicker = (
    <>
      {tab === Tab.start ? (
        <DateTimePicker
          date={start || fromPreview}
          endDate={end || toPreview}
          minDate={minDate}
          maxDate={maxDate}
          tab={tab}
          onChange={(d) => {
            setStart(d);
            if (end && d && d > end) setEnd(undefined);
          }}
          selectsStart
          inline
        />
      ) : (
        <DateTimePicker
          date={start || fromPreview}
          endDate={end || toPreview}
          minDate={minDate}
          maxDate={maxDate}
          tab={tab}
          onChange={(d) => {
            if (d && start && d >= start) setEnd(d);
            if (!start) setEnd(d);
          }}
          selectsEnd
          inline
        />
      )}
    </>
  );
  const inner = (
    <div>
      <div className={cls.picker}>
        {onlyStart && !separate && (
          <DateTimePicker
            date={start}
            endDate={end}
            minDate={minDate}
            maxDate={maxDate}
            onChange={(d) => {
              setStart(d);
            }}
            inline
          />
        )}
        {onlyEnd && !separate && (
          <DateTimePicker
            date={start}
            endDate={end}
            minDate={minDate}
            maxDate={maxDate}
            onChange={(d) => {
              setEnd(d);
            }}
            selectsEnd
            inline
          />
        )}
        {separate && separatePicker}
        {!onlyStart && !onlyEnd && !separate && (
          <DateTimePicker
            date={start}
            endDate={end}
            minDate={minDate}
            maxDate={maxDate}
            tab={tab}
            onDatesChange={(d) => {
              setStart(d[0]);
              setEnd(d[1]);
              if (d[0] && d[1]) setOpen(false);
            }}
            inline
          />
        )}

        <TimePicker
          hours={dateHours}
          minutes={dateMinutes}
          onChange={updateTime}
          tab={tab}
          start={start || fromPreview}
          end={end || toPreview}
        />
      </div>
      {!hideFooter && (
        <div className={cls.footer}>
          <Button onClick={onConfirm} variant="stroke">
            Применить
          </Button>
          <Button onClick={onReset} variant="util">
            Сброс
          </Button>
        </div>
      )}
    </div>
  );

  return (
    <div className={cn(cls.root, { [cls.root_inline]: inline || collapse })}>
      {!hideButtons && !realtorButtons && (
        <div className={cls.buttons}>
          <button
            type="button"
            data-tab-filled={!!from}
            data-tab-active={isOpen && tab === Tab.start}
            onClick={onTabClick(Tab.start)}
            disabled={onlyEnd}
          >
            <DateIcon />
            {from ||
              (fromPreview && formatDate(fromPreview, "PPpp")) ||
              "Начало"}
          </button>
          <button
            type="button"
            data-tab-filled={!!to}
            data-tab-active={isOpen && tab === Tab.end}
            onClick={onTabClick(Tab.end)}
          >
            <DateIcon />
            {to || (toPreview && formatDate(toPreview, "PPpp")) || "Конец"}
          </button>
        </div>
      )}
      {realtorButtons && (
        <div className={cls.realtorBtns}>
          <div className={cls.buttons}>
            <button
              type="button"
              data-tab-filled={!!from}
              data-tab-active={isOpen && tab === Tab.start}
              onClick={onTabClick(Tab.start)}
              disabled={onlyEnd}
            >
              <DateIcon />
              {from ||
                (fromPreview && formatDate(fromPreview, "PPpp")) ||
                "Начало"}
            </button>
            <button
              type="button"
              data-tab-filled={!!to}
              data-tab-active={isOpen && tab === Tab.end}
              onClick={onTabClick(Tab.end)}
            >
              <DateIcon />
              {to || (toPreview && formatDate(toPreview, "PPpp")) || "Конц"}
            </button>
          </div>
        </div>
      )}
      {/* eslint-disable-next-line no-nested-ternary */}
      {inner}
    </div>
  );
};
